package com.spsoft.vatoutinv.service.commoninvoice.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.spsoft.core.enums.ResponseEnum;
import com.spsoft.core.exception.BusinessException;
import com.spsoft.core.utils.SecurityUtils;
import com.spsoft.system.entity.NvatTaxhardwarelunit;
import com.spsoft.system.mapper.NvatOutInvoiceDetailsMapper;
import com.spsoft.system.mapper.NvatOutInvoiceItemsMapper;
import com.spsoft.system.mapper.NvatTaxhardwarelunitMapper;
import com.spsoft.system.model.vo.InvoiceItemVo;
import com.spsoft.system.model.vo.InvoiceVo;
import com.spsoft.vatoutinv.constants.DictConstant;
import com.spsoft.vatoutinv.entity.vmsclassifycode.VmsClassifyCode;
import com.spsoft.vatoutinv.enums.CommonEnum;
import com.spsoft.vatoutinv.enums.ExcelDownloadEnum;
import com.spsoft.vatoutinv.enums.TdysEnum;
import com.spsoft.vatoutinv.enums.YhzcbsEnum;
import com.spsoft.vatoutinv.mapper.VmsClassifyCodeMapper;
import com.spsoft.vatoutinv.mapper.VmsFullOutInvoiceDetailsMapper;
import com.spsoft.vatoutinv.mapper.VmsFullOutInvoiceItemsMapper;
import com.spsoft.vatoutinv.service.commoninvoice.CommonInvoiceService;
import com.spsoft.vatoutinv.service.translate.impl.DictTranslate;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;

/**
 * 公共发票信息实现类
 *
 * @author : chenxudong
 * @date : 2024/4/9 10:33
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CommonInvoiceServiceImpl implements CommonInvoiceService {

    public static final String LOG_MSG = "(公共发票信息实现类)";

    private final DictTranslate dictTranslate;

    private final NvatOutInvoiceDetailsMapper nvatOutInvoiceDetailsMapper;

    private final NvatOutInvoiceItemsMapper nvatOutInvoiceItemsMapper;

    private final VmsFullOutInvoiceDetailsMapper vmsFullOutInvoiceDetailsMapper;

    private final VmsFullOutInvoiceItemsMapper vmsFullOutInvoiceItemsMapper;

    private final NvatTaxhardwarelunitMapper nvatTaxhardwarelunitMapper;

    private final VmsClassifyCodeMapper vmsClassifyCodeMapper;

    @Override
    public InvoiceVo queryInvoice(String fpdm, String fphm, boolean queryItem) {
        // 发票号码不能为空
        if (StringUtils.isBlank(fphm)) {
            throw new BusinessException(ResponseEnum.LZFPHM_EMPTY_ERROR);
        }
        // 返回数据
        InvoiceVo invoiceVo;
        String deptCode = SecurityUtils.getDeptCode();
        if (StringUtils.isNotBlank(fpdm)) {
            invoiceVo = nvatOutInvoiceDetailsMapper.queryInvoice(fpdm, fphm, deptCode);
            if (invoiceVo != null) {
                log.info("{}判断发票代码：{}，发票号码：{}为税控发票", LOG_MSG, fpdm, fphm);
                invoiceVo.setSjkly(CommonEnum.SJKLY_SK.getKey());
                // 差额征税判断并赋值
                if (CommonEnum.TAXATION_METHOD_2.getKey().equals(invoiceVo.getZsfs())) {
                    invoiceVo.setCezslxdm(CommonEnum.CEZS_02.getKey());
                }
                // 判断税控发票是否需要补全销售方信息
                if (StringUtils.isBlank(invoiceVo.getXsfnsrsbh())) {
                    LambdaQueryWrapper<NvatTaxhardwarelunit> query = new LambdaQueryWrapper<>();
                    query.eq(NvatTaxhardwarelunit::getSbdwid, invoiceVo.getSbdwid());
                    NvatTaxhardwarelunit info = nvatTaxhardwarelunitMapper.selectOne(query);
                    if (info != null) {
                        // 补全销售方名称、税号
                        invoiceVo.setXsfmc(info.getSbdwmc());
                        invoiceVo.setXsfnsrsbh(info.getNssbh());
                    }
                }
                // 是否需要查询发票明细
                if (queryItem) {
                    List<InvoiceItemVo> invoiceItemVoList = nvatOutInvoiceItemsMapper.queryInvoiceItem(invoiceVo.getId());
                    if (CollectionUtil.isEmpty(invoiceItemVoList)) {
                        throw new BusinessException(ResponseEnum.INVOICE_ITEM_NOT_FIND_ERROR);
                    }
                    // 税控发票明细序号赋值
                    for (int i = 0; i < invoiceItemVoList.size(); i++) {
                        InvoiceItemVo invoiceItemVo = invoiceItemVoList.get(i);
                        invoiceItemVo.setMxxh((long) (i + 1));
                        // 单价数量特殊处理
                        if (invoiceItemVo.getDj1() != null) {
                            invoiceItemVo.setDj(invoiceItemVo.getDj1().toPlainString());
                        }
                        if (invoiceItemVo.getSl1() != null) {
                            invoiceItemVo.setSl(invoiceItemVo.getSl1().toPlainString());
                        }
                        // 扣除额特殊处理
                        if (invoiceVo.getKce() != null
                                && invoiceVo.getKce().compareTo(BigDecimal.ZERO) != 0) {
                            invoiceItemVo.setKce(invoiceVo.getKce());
                        }
                        // 单位特殊处理
                        String dw = dictTranslate.translate(DictConstant.VMS_JLDW, invoiceItemVo.getDw());
                        invoiceItemVo.setDw(StringUtils.isNotBlank(dw) ? dw : invoiceItemVo.getDw());
                        // 将税控优惠政策标识转为数电优惠政策标识
                        invoiceItemVo.setYhzcbs(convertYhzcbs(invoiceItemVo.getZzstsgl()));
                        // 判断税控发票的特定要素类型代码，只有手工开票存在不动产发票
                        if (CommonEnum.DATA_SOURCE_1.getKey().equals(invoiceVo.getSjly())) {
                            LambdaQueryWrapper<VmsClassifyCode> query = new LambdaQueryWrapper<>();
                            query.eq(VmsClassifyCode::getSphfwssflhbbm, invoiceItemVo.getSphfwssflhbbm());
                            query.eq(VmsClassifyCode::getDeptCode, invoiceVo.getQydjid());
                            VmsClassifyCode vmsClassifyCode = vmsClassifyCodeMapper.selectOne(query);
                            if (vmsClassifyCode != null && StringUtils.isNotBlank(vmsClassifyCode.getTdyslxdm())) {
                                invoiceVo.setTdys(vmsClassifyCode.getTdyslxdm());
                                if (StrUtil.equalsAny(vmsClassifyCode.getTdyslxdm(), TdysEnum.TDYS_05.getCode(), TdysEnum.TDYS_06.getCode())) {
                                    invoiceVo.setSfbdc(CommonEnum.SFBDC_YES.getKey());
                                }
                            }
                        }
                    }
                    invoiceVo.setInvoiceItemVoList(invoiceItemVoList);
                }
            } else {
                log.info("{}判断发票代码：{}，发票号码：{}为进项发票", LOG_MSG, fpdm, fphm);
                // invoiceVo.setSjkly(CommonEnum.SJKLY_JX.getKey());
                // todo 查询进项发票的数据库
                throw new BusinessException(ResponseEnum.HZQRD_NO_INVOICE_ERROR);
            }
        } else {
            log.info("{}判断发票号码：{}为数电发票", LOG_MSG, fphm);
            invoiceVo = vmsFullOutInvoiceDetailsMapper.queryInvoice(fphm, deptCode);
            if (invoiceVo == null) {
                throw new BusinessException(ResponseEnum.HZQRD_NO_INVOICE_ERROR);
            }
            invoiceVo.setSjkly(CommonEnum.SJKLY_SD.getKey());
            // 是否需要查询发票明细
            if (queryItem) {
                // 查询发票明细信息
                List<InvoiceItemVo> invoiceItemVoList = vmsFullOutInvoiceItemsMapper.queryInvoiceItem(invoiceVo.getId());
                if (CollectionUtil.isEmpty(invoiceItemVoList)) {
                    throw new BusinessException(ResponseEnum.INVOICE_ITEM_NOT_FIND_ERROR);
                }
                invoiceVo.setInvoiceItemVoList(invoiceItemVoList);
            }
        }
        return invoiceVo;
    }

    /**
     * 通过税控增值税特殊管理将税控优惠政策标识转为数电优惠政策标识
     * @param zzstsgl 税控增值税特殊管理
     * @return 数电优惠政策标识
     */
    private String convertYhzcbs(String zzstsgl) {
        String yhzcbs;
        if (StringUtils.isBlank(zzstsgl)) {
            yhzcbs = StringUtils.EMPTY;
        } else {
            if (zzstsgl.contains("null")) {
                yhzcbs = StringUtils.EMPTY;
            } else {
                switch (zzstsgl) {
                    case "1":
                        yhzcbs = YhzcbsEnum._03.getKey();
                        break;
                    case "免税":
                        yhzcbs = YhzcbsEnum._03.getKey();
                        break;
                    case "2":
                        yhzcbs = YhzcbsEnum._02.getKey();
                        break;
                    case "稀土产品":
                        yhzcbs = YhzcbsEnum._02.getKey();
                        break;
                    case "3":
                        yhzcbs = YhzcbsEnum._01.getKey();
                        break;
                    case "简易征收":
                        yhzcbs = YhzcbsEnum._01.getKey();
                        break;
                    case "4":
                        yhzcbs = YhzcbsEnum._12.getKey();
                        break;
                    case "5":
                        yhzcbs = YhzcbsEnum._13.getKey();
                        break;
                    case "6":
                        yhzcbs = YhzcbsEnum._06.getKey();
                        break;
                    case "7":
                        yhzcbs = YhzcbsEnum._07.getKey();
                        break;
                    case "8":
                        yhzcbs = YhzcbsEnum._15.getKey();
                        break;
                    case "9":
                        yhzcbs = YhzcbsEnum._14.getKey();
                        break;
                    case "10":
                        yhzcbs = YhzcbsEnum._11.getKey();
                        break;
                    case "11":
                        yhzcbs = YhzcbsEnum._16.getKey();
                        break;
                    case "12":
                        yhzcbs = YhzcbsEnum._17.getKey();
                        break;
                    case "13":
                        yhzcbs = YhzcbsEnum._05.getKey();
                        break;
                    case "14":
                        yhzcbs = YhzcbsEnum._04.getKey();
                        break;
                    case "15":
                        yhzcbs = YhzcbsEnum._09.getKey();
                        break;
                    case "16":
                        yhzcbs = YhzcbsEnum._10.getKey();
                        break;
                    case "17":
                        yhzcbs = YhzcbsEnum._08.getKey();
                        break;
                    case "按5%简易征收":
                        yhzcbs = YhzcbsEnum._09.getKey();
                        break;
                    case "按5a简易征收":
                        yhzcbs = YhzcbsEnum._09.getKey();
                        break;
                    case "按3%简易征收":
                        yhzcbs = YhzcbsEnum._08.getKey();
                        break;
                    case "按3a简易征收":
                        yhzcbs = YhzcbsEnum._08.getKey();
                        break;
                    case "不征税":
                        yhzcbs = YhzcbsEnum._04.getKey();
                        break;
                    default:
                        yhzcbs = StringUtils.EMPTY;
                }
            }
        }
        return yhzcbs;
    }

    @Override
    public void downloadExcel(String excelType, HttpServletResponse response) {
        try {
            ExcelDownloadEnum excelEnum = ExcelDownloadEnum.getEnumByExcelType(excelType);
            if (excelEnum == null) {
                throw new BusinessException(ResponseEnum.BUSINESS_EXCEL_TYPE_ERROR);
            }
            // 获取Excel模板的系统存放路径
            String rootPath = "download/" + excelEnum.getExcelName();
            InputStream fis = Thread.currentThread().getContextClassLoader().getResourceAsStream(rootPath);
            if (fis == null) {
                log.error("{}模板下载异常,读取不到文件", LOG_MSG);
                throw new BusinessException(ResponseEnum.BUSINESS_EXCEL_TEMPLATE_ERROR);
            }
            XSSFWorkbook workbook = new XSSFWorkbook(fis);
            // 通知类型
            response.reset();
            response.setCharacterEncoding(StandardCharsets.UTF_8.name());
            response.setContentType("application/vnd.ms-excel;charset=UTF-8");
            // 获取Excel下载返回给用户的文件名
            String finalFileName = excelEnum.getFileName();
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(finalFileName, "UTF8") + ".xlsx");
            workbook.write(response.getOutputStream());
            log.info("{}excel模板下载成功", LOG_MSG);
        } catch (Exception e) {
            log.error("{}excel模板下载异常", LOG_MSG, e);
            throw new BusinessException(ResponseEnum.BUSINESS_EXCEL_TEMPLATE_ERROR);
        }
    }
}
